package it.softphone.commons.service.mail;


import it.softphone.commons.exception.NullParameterException;
import it.softphone.commons.service.mail.MailService.Message;

import javax.mail.Authenticator;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.apache.commons.configuration.Configuration;

public class MailServiceFactory {
	
	static class MessageImpl implements MailService.Message {
		
		protected String from;
		protected java.util.Collection<String> to;
		protected String subject;
		protected String body;
		
		
		public it.softphone.commons.service.mail.MailService.Message setFrom(String from) {
			this.from = from;
			return this;
		}

		public it.softphone.commons.service.mail.MailService.Message setTo(java.util.Collection<String> to) {
			this.to = to;
			return this;
		}

		public it.softphone.commons.service.mail.MailService.Message setSubject(String subject) {
			this.subject = subject;
			return this;
		}

		public Message setBody(String body) {
			this.body = body;
			return this;
		}
		
		public void checkValidity() {
			if( from == null ) throw new NullParameterException("from");
			if( to == null ) throw new NullParameterException("to array");
			if( subject == null ) throw new NullParameterException("subject");
			if( body == null ) throw new NullParameterException("body");
			
			if( to.isEmpty() ) throw new IllegalArgumentException( "to array is empty!");			
		}

	};

	static class SimpleMessageImpl extends MessageImpl implements MailService.SimpleMessage {
		
	}
	
	static class HtmlMessageImpl extends MessageImpl implements MailService.HtmlMessage {

	}
	
	
	static class DefaultMailServiceImpl implements MailService {

		private final Session mailSession;
		
		public DefaultMailServiceImpl(Session session) {
			super();
			this.mailSession = session;
		}

		public void sendMail( Message m ) throws MessagingException {
			if( m == null ) throw new NullParameterException("m");
			
			MessageImpl mm = (MessageImpl) m;
			
			mm.checkValidity();
			
			javax.mail.Message simpleMessage = new MimeMessage(mailSession);
			
			InternetAddress fromAddress = null;

			fromAddress = new InternetAddress(mm.from);
			
			simpleMessage.setFrom(fromAddress);
			simpleMessage.setSubject(mm.subject);
			if( m instanceof HtmlMessage ) {
				simpleMessage.setContent( mm.body, "text/html");
			}
			else {
				simpleMessage.setText(mm.body);
			}
			
			if( mm.to.size() == 1 ) {
	
				InternetAddress toAddress = new InternetAddress( mm.to.iterator().next() );
				
				simpleMessage.setRecipient(RecipientType.TO, toAddress);
			}
			else {
				for( String toAddress : mm.to ) {
					
					simpleMessage.addRecipient(RecipientType.TO, new InternetAddress(toAddress));
					
				}
			}
			Transport.send(simpleMessage);			
			
		}


		public SimpleMessage newSimpleMessage() {
			return new SimpleMessageImpl();
		}

		public HtmlMessage newHtmlMessage() {
			return new HtmlMessageImpl();
		}

	}
	
	static class DefaultAuthenticator extends Authenticator {

		final PasswordAuthentication auth;
		
		public DefaultAuthenticator(PasswordAuthentication pa) {
			super();
			this.auth = pa;
		}
		public DefaultAuthenticator(Configuration conf) {
			super();
			this.auth = new PasswordAuthentication( conf.getString("mail.smtp.username"), conf.getString("mail.smtp.password"));;
		}

		@Override
		protected PasswordAuthentication getPasswordAuthentication() {
			return auth;
		}
		
	}
	/**
	 * Initialize Mail Service<br>
	 * 
	 * Configuration parameters
	 * <pre>
	 * mail.smtp.host
	 * mail.smtp.port
	 * </pre>
	 * 
	 * @param conf
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static MailService getMailService( Configuration conf ) {
		
		java.util.Properties props = new java.util.Properties();
		
		java.util.Iterator<String> keys = conf.getKeys("mail");
		while( keys.hasNext() ) {
			
			String key = keys.next();
			String value = conf.getString(key);
			props.setProperty(key, value);
		}
		
		boolean auth = conf.getBoolean("mail.smtp.auth", false);
		
		Session mailSession = (auth ) ? Session.getDefaultInstance(props, new DefaultAuthenticator(conf)) : Session.getDefaultInstance(props);
	
		return new DefaultMailServiceImpl(mailSession);
	}
}
